package com.terrynoya.fight.scriptEngine.interpreter
{
	import com.terrynoya.fight.evaluation.Token;
	import com.terrynoya.fight.scriptEngine.TokenNode;
	import com.terrynoya.fight.scriptEngine.TokenType;

	public class Interpreter
	{
		public function Interpreter()
		{
			
		}
		
		public function excute(node:TokenNode):Number
		{
			return this.statement(node);
		}
		
		private function statement(node:TokenNode):Number
		{
			if(node.type == TokenType.IF)
			{
				return ifStatement(node);
			}
			else
			{
				return exp(node);
			}
			return 0;
		}
		
		private function ifStatement(node:TokenNode):Number
		{
			return 0;
		}
		
		private function exp(node:TokenNode):*
		{
			switch(node.type)
			{
				case TokenType.LOGIC_OPER:
				{
					return this.logicExp(node);
					break;
				}
				case TokenType.COMPARE_OPER:
				{
					return this.compareExp(node);
					break;
				}
				case TokenType.OPER:
				{
					return this.term(node);
					break;
				}
				case TokenType.CONST:
				{
					return Number(node.value);
					break;
				}
			}
			return 0;
		}
		
		private function logicExp(node:TokenNode):Boolean
		{
			var lhr:Boolean = this.compareExp(node.getChildAt(0));
			var rhr:Boolean = this.compareExp(node.getChildAt(1));
			switch(node.value)
			{
				case "&&":
				{
					return lhr && rhr;
				}
				case "||":
				{
					return lhr || rhr;
				}
			}
			return false;
		}
		
		private function compareExp(node:TokenNode):Boolean
		{
			if(node.type == TokenType.CONST)
			{
				return Boolean(node.value);
			}
			var lhr:Number = this.term(node.getChildAt(0));
			var rhr:Number = this.term(node.getChildAt(1));
			switch(node.value)
			{
				case ">":
				{
					return lhr > rhr;
				}
				case ">=":
				{
					return lhr >= rhr;
				}
				case "<":
				{
					return lhr < rhr;
				}
				case "<=":
				{
					return lhr <= rhr;
				}
				case "==":
				{
					return lhr == rhr;
				}
			}
			return false;
		}
		
		private function term(node:TokenNode):Number
		{
			if(node.type == TokenType.CONST)
			{
				return Number(node.value);
			}
			var lhr:Number = factor(node.getChildAt(0));
			var rhr:Number = factor(node.getChildAt(1));
			switch(node.value)
			{
				case "+":
				{
					return lhr + rhr; 				
				}
				case "-":
				{
					return lhr - rhr; 				
				}
				case "*":
				{
					return lhr * rhr; 				
				}
				case "/":
				{
					return lhr / rhr; 				
				}
			}
			return 0;
		}
		
		private function factor(node:TokenNode):Number
		{
			switch(node.type)
			{
				case TokenType.CONST:
				{
					return Number(node.value);
					break;
				}
				case TokenType.OPER:
				{
					return this.term(node);
					break;
				}
			}
			return 0;
		}
	}
}